/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import jsbn from './jsbn'
// const jsbn = require('./jsbn') 

var BigInteger = jsbn.BigInteger;
const BASE_COUNT = 100;
const LONG_COUNT = 1000;
const MAX_COUNT  = 100000;
 
/* Returns a string representing the BigInteger bi. */
function toString_Test() {    
    var bi = new BigInteger('147852478569325412365477412589966523362563987415236478895412365899874564897984827489132524785693254123654774125899665233625639874152364788954125899665233625639874152364788954123658998745648979848274891325247856932541236547741258996652336256398741523647889541258996652336256398741523647889541236589987456489798482748913252478569325412365477412589966523362563987415236478895412589966523362563987415236478895412365899874564897984827489132524785693254123654774125899665233625639874152364788954125899665233625639874152364788954123658998745648979848274891325247856932541236547741258996652336256398741523647889541236589');
    let result
    let startTime = Date.now()
    for (let i=0;i<BASE_COUNT;i++) {
        result = bi.toString()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_toString: " + time +" ms")   
    areEqual('147852478569325412365477412589966523362563987415236478895412365899874564897984827489132524785693254123654774125899665233625639874152364788954125899665233625639874152364788954123658998745648979848274891325247856932541236547741258996652336256398741523647889541258996652336256398741523647889541236589987456489798482748913252478569325412365477412589966523362563987415236478895412589966523362563987415236478895412365899874564897984827489132524785693254123654774125899665233625639874152364788954125899665233625639874152364788954123658998745648979848274891325247856932541236547741258996652336256398741523647889541236589', result) 

    // print(result)
} 

/* number negation */
function negate_Test() {    
    var bi = new BigInteger('5613465486798645616513648941651316545684698465165165116513648941651316545684698465165165116513648941651316545684698465165165116513648941651316545131545684698465165165116513648941651316545684698465165165116513648941651316545684698465165165116513648941651316545131545684698465165165116513648941651316545684698465165165116513648941651316545684698465165165116513648941651316545131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516513659743651656565');
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.negate()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_negate: " + time +" ms")   
    areEqual('-5613465486798645616513648941651316545684698465165165116513648941651316545684698465165165116513648941651316545684698465165165116513648941651316545131545684698465165165116513648941651316545684698465165165116513648941651316545684698465165165116513648941651316545131545684698465165165116513648941651316545684698465165165116513648941651316545684698465165165116513648941651316545131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516511651364894165131654568469846516516513659743651656565', result.toString()) 

    // print(result)
} 

/* Returns a BigInteger equal to the absolute value of bi */
function abs_Test() {    
    var bi = new BigInteger('-5641321984984198416845849354984645893746985849658477491659182391823918239812356413219849841984168458493549846458937469858496584774916591823918239182398123458937469858496584774916591823918239182398123564132198498419841684584935498464589374698584965847749165918239182391823981234589374698584965847749165918239182391823981235641321984984198416845849354984645893746985849658477491659182391823918239812345893746985849658477491659182391823918239812356413219849841984168458493549846458937469858496584774916591823918239182398123');
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.abs()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_abs: " + time +" ms")   
    areEqual('5641321984984198416845849354984645893746985849658477491659182391823918239812356413219849841984168458493549846458937469858496584774916591823918239182398123458937469858496584774916591823918239182398123564132198498419841684584935498464589374698584965847749165918239182391823981234589374698584965847749165918239182391823981235641321984984198416845849354984645893746985849658477491659182391823918239812345893746985849658477491659182391823918239812356413219849841984168458493549846458937469858496584774916591823918239182398123', result.toString()) 

    // print(result)
} 

/* Compare to BigIntegers. The return value will be a negative JavaScript number if bi is less than other, a positive number if bi is greater than other, and 0 if bi and other represents the same integer. */
function compareTo_Test() {    
    let data = '987456489798482748913252478569325412365477412589966523362563987415236478895412365899874564897984827489132524785693254123654774125899665233625639874152364788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897984827489132524785693254123654774125899665233625639874152364788954123658998745648979848274891325247856932541236547741258996652336256398741523647889541236589'
    var bi = new BigInteger(data);
    var bi2 = new BigInteger(data);
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.compareTo(bi2)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_compareTo: " + time +" ms")   
    areEqual(0, result) 

    // print(result)
} 

/* Returns the number of bits used to store bi as a JavaScript number. */
function bitLength_Test() {    
    var bi = new BigInteger('987456489798482748913252478569325412365477412589966523362563987415236478895412365899874564897984827489132524785693254123654774125899665233625639874152364788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897984827489132524785693254123654774125899665233625639874152364788954123658998745648979848274891325247856932541236547741258996652336256398741523647889541236589');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.bitLength()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_bitLength: " + time +" ms")   
    areEqual('1794', result.toString()) 

    // print(result)
} 

/* Returns a BigInteger with the value of (bi mod m). */
function mod_Test() {    
    var bi = new BigInteger('874152364788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897874152364788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899123456789');
    var m = new BigInteger('147852369');
    let result
    let startTime = Date.now()
    for (let i=0;i<1000;i++) {
        result = bi.mod(m)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_mod: " + time +" ms")   
    areEqual('74412596', result.toString()) 

    // print(result)
} 

/* Returns a BigInteger with the value of (biexponent mod m). this^e % m (HAC 14.85) */
function modPow_Test() {    
    var bi = new BigInteger('874152364788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897874152364788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899123456789');
    var e1 = new BigInteger('3');
    var m = new BigInteger('1457879654465');
    let result
    let startTime = Date.now()
    for (let i=0;i<BASE_COUNT;i++) {
        result = bi.modPow(e1,m)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_modPow: " + time +" ms")   
    areEqual('464368186134', result.toString()) 

    // print(result)
} 

/* this^e % m, 0 <= e < 2^32 */
function modPowInt_Test() {    
    var bi = new BigInteger('64788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648978741523647889541236589987647889541236589987456489796478895412365899874564897964788954123658998745648979647889541236589987456489787415236478895412365899876478895412365899874564897964788954123658998745648979647889541236589987456489796478895412365899874564897874152364788954123658998764788954123658998745648979647889541236589987456489796478895412365899874564897964788954123658998745648978741523647889541236589987');
    var e = '111';
    var m = new BigInteger('78988948948943928449123');
    let result
    let startTime = Date.now()
    for (let i=0;i<BASE_COUNT;i++) {
        result = bi.modPowInt(e,m)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_modPowInt: " + time +" ms")   
    areEqual('4994739201670284131365', result.toString()) 

    // print(result)
} 

/* clone */
function clone_Test() {   
    let data = '54231545546536143625443652463254165341651341365456648459809899898979741461114693684483489757556764776478746938745636445566344529843542934524655464535165431565467847899796287295928745141545647768765687272764287546243918239182391823981266344529843542934524655464535165431565467847899796287295928745141545647768765687272764287546243918239182391823984354293452465546453516543156546784789979628729592874514154564776876568727276428754624391823918239182398126634452998123'  
    var bi = new BigInteger(data);
    let result
    let startTime = Date.now()
    for (let i=0;i<10000;i++) {
        result = bi.clone()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_clone: " + time +" ms")   
    areEqual(data, result.toString()) 

    // print(result)
} 

/* return value as integer */
function intValue_Test() {    
    var bi = new BigInteger('1.918178999');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.intValue()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_intValue: " + time +" ms")   
    areEqual(1918178999, result) 

    // print(result)
} 

/* return value as byte */
function byteValue_Test() {    
    var bi = new BigInteger('126');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.byteValue()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_byteValue: " + time +" ms")   
    areEqual(126, result) 

    // print(result)
} 

/* return value as short (assumes DB>=16) */
function shortValue_Test() {    
    var bi = new BigInteger('12349');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.shortValue()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_shortValue: " + time +" ms")   
    areEqual(12349, result) 

    // print(result)
} 

/* 0 if this == 0, 1 if this > 0 */
function signum_Test() {    
    var bi = new BigInteger('54231545546536143625443652463254165341651341365456648459809899898979741461114693684483489757556764776478746938745636445566344529843542934524655464535165431565467847899796287295928745141545647768765687272764287546243918239182391823981266344529843542934524655464535165431565467847899796287295928745141545647768765687272764287546243918239182391823984354293452465546453516543156546784789979628729592874514154564776876568727276428754624391823918239182398126634452998123');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.signum()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_signum: " + time +" ms")   
    areEqual(1, result) 

    // print(result)
} 

/* convert to bigendian byte array */
function toByteArray_Test() {    
    var bi = new BigInteger('125');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.toByteArray()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_toByteArray: " + time +" ms")   
    areEqual('125', result.toString()) 

    // print(result)
} 

/* equals */
function equals_Test() {    
    let data = '54231545546536143625443652463254165341651341365456648459809899898979741461114693684483489757556764776478746938745636445566344529843542934524655464535165431565467847899796287295928745141545647768765687272764287546243918239182391823981266344529843542934524655464535165431565467847899796287295928745141545647768765687272764287546243918239182391823984354293452465546453516543156546784789979628729592874514154564776876568727276428754624391823918239182398126634452998123'  
    var bi = new BigInteger(data);
    var bi2 = new BigInteger(data+'0');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.equals(bi2)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_equals: " + time +" ms")   
    areEqual(false, result) 

    // print(result)
} 

/* return min */
function min_Test() {    
    var b1 = new BigInteger('91823918234212432432423423442233918239812391823911487434524423564238239182398123');
    var b2 = new BigInteger('91823918234212432432423423442233918239812391823911487434524423564238239182398120');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = b1.min(b2)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_min: " + time +" ms")   
    areEqual(b2, result) 

    // print(result)
} 

/* return max */
function max_Test() {    
    var b1 = new BigInteger('91823918234212432432423423442233918239812391823911487434524423564238239182398123');
    var b2 = new BigInteger('91823918234212432432423423442233918239812391823911487434524423564238239182398120');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = b1.max(b2)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_max: " + time +" ms")   
    areEqual(b1, result) 

    // print(result)
} 

/* this & a */
function and_Test() {    
    var b1 = new BigInteger('445144341234156546624546214563413265446532441651213465324165423146542345325462345612345146856094685465715136453264612346254362561565713291650494514561221654843523541554526545435453424416512134653241654231465423453254623456123451468560946854657151364532646123462543625615657132916504945145612216548435235415545265454354534');
    var b2 = new BigInteger('4524313241234347857354382441651213465324165423146542345325462345612345146856094685465715136453264612346254362561565713291650494514561221654843523541554526545435453465354615486745869348965496785946795487976577889564779878765897758967798567795684778965');
    let result
    let startTime = Date.now()
    for (let i=0;i<10000;i++) {
        result = b1.and(b2)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_and: " + time +" ms")   
    areEqual('49039925743113082565650245296789154714548273670596230291295507745576856959306069714112159298861624752125305083105197587978184328331286421952485447883741900324768837119035589742184858322824939899534187684278551239204725748499171214019408393136275524', result.toString()) 

    // print(result)
} 

/* this | a */
function or_Test() {    
    var b1 = new BigInteger('445144341234156546624546214563413265446532441651213465324165423146542345325462345612345146856094685465715136453264612346254362561565713291650494514561221654843523541554526545435453424416512134653241654231465423453254623456123451468560946854657151364532646123462543625615657132916504945145612216548435235415545265454354534');
    var b2 = new BigInteger('4524313241234347857354382441651213465324165423146542345325462345612345146856094685465715136453264612346254362561565713291650494514561221654843523541554526545435453465354615486745869348965496785946795487976577889564779878765897758967798567795684778965');
    let result
    let startTime = Date.now()
    for (let i=0;i<10000;i++) {
        result = b1.or(b2)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_or: " + time +" ms")   
    areEqual('445144341234156546624546214563413265446532441651213465324165423146542349800735661103579921644826881820139447062881761822200477595732551158418784411349837406446500695957514139564510902877027838325551840461400656344292717126908096579245575090237048368217136766134389672876957425215843270720765233947022989194704668002857975', result.toString()) 

    // print(result)
} 

/* this ^ a */
function xor_Test() {    
    var b1 = new BigInteger('1234567898975412395416445984367548975984366446544163254493284493284138294431498492386459746787898298459542493579449572349454715173441273427473297544738578487687683754378732645443747274438544949181989111111111123224347582374578294554897564473468351324854382748234');
    var b2 = new BigInteger('17847781876344752423844182448746784859717852315443145456341565243651653445743854289734457843458347458347458344584374583244554341574157324487467848597178523154431454563415652436516534457438542897344578434583474583474583445843745832445543415741573');
    let result
    let startTime = Date.now()
    for (let i=0;i<10000;i++) {
        result = b1.xor(b2)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_xor: " + time +" ms")   
    areEqual('1234567898975412404942545018360670204240873672253189622590328942942675111728982249872019243485945146942957768677064021170135792241442400962022874097047805553174671266806147381395843459304243002667814450483871258952305956102053076730369396003873067863414805962447', result.toString()) 

    // print(result)
} 

/* this & ~a */
function andNot_Test() {    
    var b1 = new BigInteger('1234567898975412395416445984367548975984366446544163254493284493284138294431498492386459746787898298459542493579449572349454715173441273427473297544738578487687683754378732645443747274438544949181989111111111123224347582374578294554897564473468351324854382748234');
    var b2 = new BigInteger('17847781876344752423844182448746784859717852315443145456341565243651653445743854289734457843458347458347458344584374583244554341574157324487467848597178523154431454563415652436516534457438542897344578434583474583474583445843745832445543415741573');
    let result
    let startTime = Date.now()
    for (let i=0;i<10000;i++) {
        result =  b1.andNot(b2) 
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_andNot: " + time +" ms")   
    areEqual('1234567898975412391255604563191733378190528835025284008682880560391833974909457749303412772264994577834021209399083067586066081415254545572470915033814529776697253212003178436204068085163567757666634552078219742416037551946578393905341757316797793371362886484554', result.toString()) 

    // print(result)
} 

/* ~this */
function not_Test() {    
    var bi = new BigInteger('5412323448741327483478349194139442394142389541232344874132748347834919413944239414238954123234487413274834783491941394423941423895412323448741327483478349194139442394142389541232344874132748347834919413944239414238954123234487413274834783491941394423941423895412323448741327483478349194139442394142389');
    let result
    let startTime = Date.now()
    for (let i=0;i<10000;i++) {
        result = bi.not()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_not: " + time +" ms")   
    areEqual('-5412323448741327483478349194139442394142389541232344874132748347834919413944239414238954123234487413274834783491941394423941423895412323448741327483478349194139442394142389541232344874132748347834919413944239414238954123234487413274834783491941394423941423895412323448741327483478349194139442394142390', result.toString()) 

    // print(result)
} 

/* this << n */
function shiftLeft_Test() {    
    var bi = new BigInteger('12413425413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545');
    let n = 100
    let result
    let startTime = Date.now()
    for (let i=0;i<10000;i++) {
        result = bi.shiftLeft(n)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_shiftLeft: " + time +" ms")   
    areEqual('15735886176042317451344474174125430994276979108567615631478903902758777381409055876178172114276979108567615631478903902758777381409055876178172114276979108567615631478903902758777381409055876178172114276979108567615631478903902758777381409055876178172114276979108567615631478903378854568488338794689247313920', result.toString()) 

    // print(result)
} 

/* this >> n */
function shiftRight_Test() {    
    var bi = new BigInteger('15735886176042317451344474174125430994276979108567615631478903902758777381409055876178172114276979108567615631478903902758777381409055876178172114276979108567615631478903902758777381409055876178172114276979108567615631478903902758777381409055876178172114276979108567615631478903378854568488338794689247313920');
    let n = 100
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.shiftRight(n)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_shiftRight: " + time +" ms")   
    areEqual('12413425413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545', result.toString()) 

    // print(result)
} 

/* returns index of lowest 1-bit (or -1 if none) */
function getLowestSetBit_Test() {    
    var bi = new BigInteger('1024');
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.getLowestSetBit()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_getLowestSetBit: " + time +" ms")   
    areEqual(10, result) 

    // print(result)
} 

/* return number of set bits */
function bitCount_Test() {    
    var bi = new BigInteger('12413425413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545');
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.bitCount()
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_bitCount: " + time +" ms")   
    areEqual(463, result) 

    // print(result)
} 

/* Tests whether the n bit is 1 and the result is true */
function testBit_Test() {    
    var bi = new BigInteger('12413425413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545413287548476485469538769489657465987965432465542634545');
    let n = 20
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.testBit(n)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_testBit: " + time +" ms")   
    areEqual(true, result) 

    // print(result)
} 

/*  this op (1<<n) */
function setBit_Test() {    
    var bi = new BigInteger('42'); //101010  -> 101110 
    let n = 2
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.setBit(n)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_setBit: " + time +" ms")   
    areEqual('46', result.toString()) 

    // print(result)
} 

/* this & ~(1<<n) */
function clearBit_Test() {    
    var bi = new BigInteger('42'); //101010  -> 100010 
    let n = 3
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.clearBit(n)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_clearBit: " + time +" ms")   
    areEqual('34', result.toString()) 

    // print(result)
} 

/* this ^ (1<<n) */
function flipBit_Test() {    
    var bi = new BigInteger('42');  //101010  -> 111010 
    let n = 4
    let result
    let startTime = Date.now()
    for (let i=0;i<MAX_COUNT;i++) {
        result = bi.flipBit(n)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_flipBit: " + time +" ms")   
    areEqual('58', result.toString()) 

    // print(result)
} 

/* this + a */
function add_Test() {    
    var bi = new BigInteger('142341324545748467584765548147515417635654385642934857984667589471326518567489867709958493486924459827592143532314321565434698564560478944359867341564895543465986489346306435946938454069458406798648894798345698249284459824594240598295092344048954876409528604587792879582749581049242985');
    var a = new BigInteger('142341324545748467584765548147515417635654385642934857984667589471326518567489867709958493486924459827592143532314321565434698564560478944359867341564895543465986489346306435946938454069458406798648894798345698249284459824594240598295092344048954876409528604587792879582749581049242985');
    let result
    let startTime = Date.now()
    for (let i=0;i<10000;i++) {
        result = bi.add(a)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_add: " + time +" ms")   
    areEqual('284682649091496935169531096295030835271308771285869715969335178942653037134979735419916986973848919655184287064628643130869397129120957888719734683129791086931972978692612871893876908138916813597297789596691396498568919649188481196590184688097909752819057209175585759165499162098485970', result.toString()) 

    // print(result)
} 

/* this - a */
function subtract_Test() {    
    var bi = new BigInteger('142341324545748467584765548147515417635654385642934857984667589471326518567489867709958493486924459827592143532314321565434698564560478944359867341564895543465986489346306435946938454069458406798648894798345698249284459824594240598295092344048954876409528604587792879582749581049242985');
    var a = new BigInteger('142341324545748467584765548147515417635654385642934857984667589471326518567489867709958493486924459827592143532314321565434698564560478944359867341564895543465986489346306435946938454069458406798648894798345698249284459824594240598295092344048954876409528604587792879582749581049242985');
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.subtract(a)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_subtract: " + time +" ms")   
    areEqual('0', result.toString()) 

    // print(result)
} 

/* this * a */
function multiply_Test() {    
    var bi = new BigInteger('111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111');
    var a = new BigInteger('8');
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.multiply(a)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_multiply: " + time +" ms")   
    areEqual('888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888', result.toString()) 

    // print(result)
} 

/* this / a */
function divide_Test() {    
    var bi = new BigInteger('888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888');
    var a = new BigInteger('111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111');
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.divide(a)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_divide: " + time +" ms")   
    areEqual('8', result.toString()) 

    // print(result)
} 

/* this % a */
function remainder_Test() {    
    var bi = new BigInteger('7741789751429481394697889607670789917834981324916598749832748912387493281749813265913849132846193286519238479382561982357194574351623984713928479124793217491328749123865917439021849132748912374918273491723498172894719823471923874912387498123751927439177491328749123874912378958783984793324793874913024103258023540123478932013016003940912410374081932478192304781029834709812374891208749021387409127490123798402917489021374819074109375109823578935');
    var a = new BigInteger('2');
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.remainder(a)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_remainder: " + time +" ms")   
    areEqual('1', result.toString()) 

    // print(result)
} 

/*  return [this/a,this%a] */
function divideAndRemainder_Test() {    
    let data = '7741789751429481394697889607670789917834981324916598749832748912387493281749813265913849132846193286519238479382561982357194574351623984713928479124793217491328749123865917439021849132748912374918273491723498172894719823471923874912387498123751927439177491328749123874912378958783984793324793874913024103258023540123478932013016003940912410374081932478192304781029834709812374891208749021387409127490123798402917489021374819074109375109823578935'
    var bi = new BigInteger(data);
    var a = new BigInteger(data);
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.divideAndRemainder(a)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_divideAndRemainder: " + time +" ms")   
    areEqual('1,0', result.toString()) 

    // print(result)
}  

/* 1/this % m (HAC 14.61) */
function modInverse_Test() {    
    var bi = new BigInteger('123456789');
    var m = new BigInteger('987654321');
    let result
    let startTime = Date.now()
    for (let i=0;i<BASE_COUNT;i++) {
        result = bi.modInverse(m)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_modInverse: " + time +" ms")   
    areEqual('0', result.toString()) 

    // print(result)
} 

/* this^e */
function pow_Test() {    
    var bi = new BigInteger('123456789');
    var e = 64
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.pow(e)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_pow: " + time +" ms")   
    areEqual('71938029702471763814124180148475036354174929627719820393899263214368625289703695684981961609220505779251290447502562589761895642136487007463373082042317368587815684236863918164693519175852875349108126917909254145628791231027574799054236470820479460365025984027507023507408827945183789502996194212701052369602158257405543769064198300559565605829095126629039405511405436432418268986152364047178175862411460331445396820983734539587447942637500028358834354832128829101293430234615913270157028000621645922491232871930295041', result.toString()) 

    // print(result)
} 

/* Find the greatest common divisor of two integers */
function gcd_Test() {    
    var bi = new BigInteger('7193802970247176381412418014847503635417492962771982039389926321436862528970369568498196160922050577925129044750256258976189564213648700746337308204231736858781568423686391816469351917585287534910812691790925414562879123102757479905423647082047946036502598402750702350740882794518378950299619');
    var a = new BigInteger('123456789');
    let result
    let startTime = Date.now()
    for (let i=0;i<BASE_COUNT;i++) {
        result = bi.gcd(a)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_gcd: " + time +" ms")   
    areEqual('1', result.toString()) 

    // print(result)
} 

/*  A method for determining whether a BigInteger object is a possible prime number, specifying the probability parameter t */
function isProbablePrime_Test() {    
    var bi = new BigInteger('71938029702471763814124180148475036354174929627719820393899263214368625289703695684981961609220505779251290447502562589761895642136487007463373082042317368587815684236863918164693519175852875349108126917909254145628791231027574799054236470820479460365025984027507023507408827945183789502996194212701052369602158257405543769064198300559565605829095126629039405511405436432418268986152364047178175862411460331445396820983734539587447942637500028358834354832128829101293430234615913270157028000621645922491232871930295041');
    var t = 10
    let result
    let startTime = Date.now()
    for (let i=0;i<LONG_COUNT;i++) {
        result = bi.isProbablePrime(t)
    } 
    let endTime = Date.now() 
    let time = endTime - startTime
    print("jsbn_isProbablePrime: " + time +" ms")   
    areEqual(false, result) 

    // print(result)
} 
 
/* Expected results and actual results verification  */
function areEqual(expected, actual) {
    // If expected and actual are both NaN, consider them equal.
    if (expected === actual || expected !== expected && actual !== actual) {
        // print('Success')
    } else {
        let error = 
        '  Failed areEqual test' +
        '  Expected: ' + expected +
        '  Actual:   ' + actual
        ;
        throw(error) 
    }
}

// function print(s){
//     console.log(s)
// }

/*  Benchmark  */
function jsbnRun() { 
    toString_Test()
    negate_Test()
    abs_Test()
    compareTo_Test()
    bitLength_Test()
    mod_Test()
    modPow_Test()
    modPowInt_Test()
    clone_Test()
    intValue_Test()
    byteValue_Test()
    shortValue_Test()
    signum_Test()
    toByteArray_Test()
    equals_Test()
    min_Test()
    max_Test()
    and_Test()
    or_Test()
    xor_Test()
    andNot_Test()
    not_Test()
    shiftLeft_Test()
    shiftRight_Test()
    getLowestSetBit_Test()
    bitCount_Test()
    testBit_Test()
    setBit_Test()
    clearBit_Test()
    flipBit_Test()
    add_Test()
    subtract_Test()
    multiply_Test()
    divide_Test()
    remainder_Test()
    divideAndRemainder_Test() 
    modInverse_Test()
    pow_Test()
    gcd_Test()
    isProbablePrime_Test()    
} 

let loopCountForPreheat = 1;
for (let i = 0; i < loopCountForPreheat; i++) {
    jsbnRun()
}

ArkTools.waitAllJitCompileFinish();

jsbnRun()